package ngat.oss.simulation;

import ngat.phase2.*;
import ngat.util.*;

import java.util.*;
import java.io.File;
import java.text.*;

/** A simple mutable implementation of EnvironmentPredictor. */
public class BasicEnvironmentPredictor implements EnvironmentPredictor,
		PropertiesConfigurable {

	public static final int FIXED_MODE = 1;

	public static final int RANDOM_ANNUAL_MODE = 2;

	public static final int RANDOM_SEASONAL_MODE = 3;

	public static final int RANDOM_UVW_MODE = 4;

	public static final int SCENARIO_MODE = 5;

	private EnvironmentSnapshot env;

	private int mode;

	// fixed mode options.
	private int fixedSeeing = Group.CRAP;

	private boolean fixedPhotom = false;

	// random mode options.
	private double excellentFraction = 0.0;

	private double averageFraction = 0.0;

	private double poorFraction = 0.0;

	private double crapFraction = 0.0;

	private double photomFraction = 0.0;

	// night mode options.
	private EnvironmentalScenario scenario;

	public BasicEnvironmentPredictor() {
		env = new EnvironmentSnapshot();
	}

	/** Configure the model. */
	public void configure(ConfigurationProperties config) throws Exception {

		String strMode = config.getProperty("mode");
		if (strMode.equals("") || strMode == null)
			throw new IllegalArgumentException(
					"No environment model class specified");

		if (strMode.equalsIgnoreCase("fixed")) {
			mode = FIXED_MODE;
			String strSeeing = config.getProperty("seeing");
			if (strSeeing.startsWith("po"))
				fixedSeeing = Group.POOR;
			else if (strSeeing.startsWith("av"))
				fixedSeeing = Group.AVERAGE;
			else if (strSeeing.startsWith("ex"))
				fixedSeeing = Group.EXCELLENT;
			else
				fixedSeeing = Group.CRAP;

			String strExtinct = config.getProperty("extinction");
			if (strExtinct.startsWith("pho"))
				fixedPhotom = true;
			else
				fixedPhotom = false;

		} else if (strMode.equalsIgnoreCase("random.annual")) {

			mode = RANDOM_ANNUAL_MODE;

			excellentFraction = config.getDoubleValue("annual.ex.fraction");
			averageFraction = config.getDoubleValue("annual.av.fraction");
			poorFraction = config.getDoubleValue("annual.poor.fraction");
			crapFraction = config.getDoubleValue("annual.crap.fraction");

			photomFraction = config.getDoubleValue("annual.photom.fraction");

		} else if (strMode.equalsIgnoreCase("random.seasonal")) {

			mode = RANDOM_SEASONAL_MODE;

			excellentFraction = config.getDoubleValue("seasonal.ex.fraction");
			averageFraction = config.getDoubleValue("seasonal.av.fraction");
			poorFraction = config.getDoubleValue("seasonal.poor.fraction");
			crapFraction = config.getDoubleValue("seasonal.crap.fraction");

			photomFraction = config.getDoubleValue("seasonal.photom.fraction");

		} else if (strMode.equalsIgnoreCase("uvw")) {

			mode = RANDOM_UVW_MODE;

			excellentFraction = config.getDoubleValue("uvw.ex.fraction");
			averageFraction = config.getDoubleValue("uvw.av.fraction");
			poorFraction = config.getDoubleValue("uvw.poor.fraction");
			crapFraction = config.getDoubleValue("uvw.crap.fraction");

			photomFraction = config.getDoubleValue("uvw.photom.fraction");

		} else if (strMode.equalsIgnoreCase("scenario")) {

			mode = SCENARIO_MODE;

			File scfile = new File(config.getProperty("scenario.file"));
			scenario = EnvironmentalScenarioGenerator.loadScenario(scfile);

		} else
			throw new IllegalArgumentException("Unknown environment model: "
					+ strMode);

	}

	public EnvironmentSnapshot predictEnvironment(long time) {
		switch (mode) {
		case FIXED_MODE:
			env.seeing = fixedSeeing;
			env.photom = fixedPhotom;
			break;
		case RANDOM_ANNUAL_MODE:
		case RANDOM_SEASONAL_MODE:
		case RANDOM_UVW_MODE:
			double rnd = Math.random();
			if (rnd < excellentFraction)
				env.seeing = Group.EXCELLENT;
			else if (rnd < excellentFraction + averageFraction)
				env.seeing = Group.AVERAGE;
			else if (rnd < excellentFraction + averageFraction + poorFraction)
				env.seeing = Group.POOR;
			else
				env.seeing = Group.CRAP;

			double rnd2 = Math.random();
			if (rnd2 < photomFraction)
				env.photom = true;
			else
				env.photom = false;

			break;
		case SCENARIO_MODE:
			env = scenario.predictEnvironment(time);
			break;
		default:
		}
		return env;
	}

}
